package org.ielse.frame.t.volley;

import java.io.File;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

/**
 * Created by liutao on 14-3-18. <br>
 * 由于耗时，修改成异步加载 - 2015-07-13
 */
public class VolleyImageUtil {

	public interface Listener {
		void onLoadCompleted(Bitmap bitmap);
	}

	public static void asyncGetScaledBitmap(final Activity context, final String filePath, final int maxWidth, final int maxHeight,
			final Listener listener) {
		new Thread(new Runnable() {
			@Override public void run() {
				final Bitmap result = getScaledBitmap(filePath, maxWidth, maxHeight);
				context.runOnUiThread(new Runnable() {
					@Override public void run() {
						if (listener != null) listener.onLoadCompleted(result);
					}
				});
			}
		}).start();
	}

	public static void asyncGetScaledBitmap(final Activity context, final File file, final int maxWidth, final int maxHeight,
			final Listener listener) {
		asyncGetScaledBitmap(context, file.getAbsolutePath(), maxWidth, maxHeight, listener);
	}

	public static void asyncGetScaledBitmap(final Activity context, final int imageResId, final int maxWidth, final int maxHeight,
			final Listener listener) {
		new Thread(new Runnable() {
			@Override public void run() {
				final Bitmap result = getScaledBitmap(context, imageResId, maxWidth, maxHeight);
				context.runOnUiThread(new Runnable() {
					@Override public void run() {
						if (listener != null) listener.onLoadCompleted(result);
					}
				});
			}
		}).start();
	}

	public static Bitmap getScaledBitmap(File file, int maxWidth, int maxHeight) {
		return getScaledBitmap(file.getAbsolutePath(), maxWidth, maxHeight);
	}

	/**
	 * 获取缩放的bitmap
	 * 
	 * @param filePath
	 * @param maxWidth
	 * @param maxHeight
	 * @return
	 */
	public static Bitmap getScaledBitmap(String filePath, int maxWidth, int maxHeight) {
		BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
		Bitmap bitmap = null;
		// If we have to resize this image, first get the natural bounds.
		decodeOptions.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(filePath, decodeOptions);
		int actualWidth = decodeOptions.outWidth;
		int actualHeight = decodeOptions.outHeight;

		// Then compute the dimensions we would ideally like to decode to.
		int desiredWidth = getResizedDimension(maxWidth, maxHeight, actualWidth, actualHeight);
		int desiredHeight = getResizedDimension(maxHeight, maxWidth, actualHeight, actualWidth);

		// Decode to the nearest power of two scaling factor.
		decodeOptions.inJustDecodeBounds = false;
		// TODO(ficus): Do we need this or is it okay since API 8 doesn't
		// support it?
		// decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED;
		decodeOptions.inSampleSize = findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight);
		Bitmap tempBitmap = BitmapFactory.decodeFile(filePath, decodeOptions);
		// If necessary, scale down to the maximal acceptable size.
		if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth || tempBitmap.getHeight() > desiredHeight)) {
			bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth, desiredHeight, true);
			tempBitmap.recycle();
		}
		else {
			bitmap = tempBitmap;
		}
		return bitmap;
	}

	/**
	 * 获取缩放的bitmap
	 * 
	 * @param context
	 * @param imageResId
	 * @param maxWidth
	 * @param maxHeight
	 * @return
	 */
	public static Bitmap getScaledBitmap(Context context, int imageResId, int maxWidth, int maxHeight) {
		BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
		Bitmap bitmap = null;
		// If we have to resize this image, first get the natural bounds.
		decodeOptions.inJustDecodeBounds = true;
		BitmapFactory.decodeResource(context.getResources(), imageResId, decodeOptions);
		int actualWidth = decodeOptions.outWidth;
		int actualHeight = decodeOptions.outHeight;

		// Then compute the dimensions we would ideally like to decode to.
		int desiredWidth = getResizedDimension(maxWidth, maxHeight, actualWidth, actualHeight);
		int desiredHeight = getResizedDimension(maxHeight, maxWidth, actualHeight, actualWidth);

		// Decode to the nearest power of two scaling factor.
		decodeOptions.inJustDecodeBounds = false;
		// TODO(ficus): Do we need this or is it okay since API 8 doesn't
		// support it?
		// decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED;
		decodeOptions.inSampleSize = findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight);
		Bitmap tempBitmap = BitmapFactory.decodeResource(context.getResources(), imageResId, decodeOptions);
		// If necessary, scale down to the maximal acceptable size.
		if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth || tempBitmap.getHeight() > desiredHeight)) {
			bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth, desiredHeight, true);
			tempBitmap.recycle();
		}
		else {
			bitmap = tempBitmap;
		}
		return bitmap;
	}

	/**
	 * Returns the largest power-of-two divisor for use in downscaling a bitmap
	 * that will not result in the scaling past the desired dimensions.
	 * 
	 * @param actualWidth
	 *            Actual width of the bitmap
	 * @param actualHeight
	 *            Actual height of the bitmap
	 * @param desiredWidth
	 *            Desired width of the bitmap
	 * @param desiredHeight
	 *            Desired height of the bitmap
	 */
	private static int findBestSampleSize(int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
		double wr = (double) actualWidth / desiredWidth;
		double hr = (double) actualHeight / desiredHeight;
		double ratio = Math.min(wr, hr);
		float n = 1.0f;
		while ((n * 2) <= ratio) {
			n *= 2;
		}

		return (int) n;
	}

	/**
	 * Scales one side of a rectangle to fit aspect ratio.
	 * 
	 * @param maxPrimary
	 *            Maximum size of the primary dimension (i.e. width for max
	 *            width), or zero to maintain aspect ratio with secondary
	 *            dimension
	 * @param maxSecondary
	 *            Maximum size of the secondary dimension, or zero to maintain
	 *            aspect ratio with primary dimension
	 * @param actualPrimary
	 *            Actual size of the primary dimension
	 * @param actualSecondary
	 *            Actual size of the secondary dimension
	 */
	private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, int actualSecondary) {
		// If no dominant value at all, just return the actual.
		if (maxPrimary == 0 && maxSecondary == 0) {
			return actualPrimary;
		}

		// If primary is unspecified, scale primary to match secondary's scaling
		// ratio.
		if (maxPrimary == 0) {
			double ratio = (double) maxSecondary / (double) actualSecondary;
			return (int) (actualPrimary * ratio);
		}

		if (maxSecondary == 0) {
			return maxPrimary;
		}

		double ratio = (double) actualSecondary / (double) actualPrimary;
		int resized = maxPrimary;
		if (resized * ratio > maxSecondary) {
			resized = (int) (maxSecondary / ratio);
		}
		return resized;
	}

}